LL_RTC_Init and LL_RTC_DeInit APIs migration

The LL initialization and de-initialization functions previously available in the stm32tnxx_ll_rtc.c files within HAL1 are no longer present in HAL2. In HAL2, all LL C files ( stm32tnxx_ll_rtc.c) have been removed, leaving only the LL header files ( stm32tnxx_ll_rtc.h) that contain static inline functions.

If users need to initialize or de-initialize RTC using the LL layer, they have two methods:

  • Utilize STM32CubeMX2 Code Generation: Rely on STM32CubeMX2 to generate code with the LL layer for RTC initialization and de-initialization.

  • Replace manually the initialization and de-initialization functionsReplace the LL_RTC_Init and LL_RTC_DeInit functions

    manually with equivalent sequences using the static inline functions provided in the stm32tnxx_ll_rtc.h file, tailored to their specific configuration and requirements.

This approach ensures that the initialization and de-initialization sequences are precisely addressing the given use case based on the LL static inline functions provided in the stm32tnxx_ll_rtc.h header file. The sequences offer improved footprint optimization compared to the previous LL initialization functions found in stm32tnxx_ll_rtc.c.

Related concept: Remove stm32tnxx_ll_ppp.c files

Method 1: Utilize STM32CubeMX2 Code Generation

LL RTC configuration panel

Create a new project with the STM32CubeMX2, then start the initialization and the main configuration.

Project configuration panel

LL RTC main features configuration

Configure the RTC main features.

RTC main feature configuration

LL RTC configuration panel

Create a new project with the STM32CubeMX2, then start the initialization and the main configuration.

Project configuration panel

LL RTC advanced features configuration

Configure the advanced RTC features.

RTC advanced feature configuration

GPIO configuration

Configure GPIO pins.

RTC GPIO configuration

NVIC configuration

Configure the NVIC in case of an interrupt.

RTC NVIC configuration

Generated RTC initialization and de-initialization sequences

The RTC initialization sequence is generated in the mx_rtc_init function in the mx_rtc.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

Related concepts:

STM32CubeMX2 Generated : RTC initialization sequence

Topic

Code Snippet HAL1

Code Snippet HAL2

Init and config sequence function

static void MX_RTC_Init(void)
{

  LL_RTC_InitTypeDef RTC_InitStruct = {0};
  LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
  LL_RTC_DateTypeDef RTC_DateStruct = {0};
  LL_RTC_AlarmTypeDef RTC_AlarmStruct = {0};

  if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSI)
  {
    LL_RCC_ForceRTCDomainReset();
    LL_RCC_ReleaseRTCDomainReset();
    LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);
  }

  /* Peripheral clock enable */
  LL_RCC_EnableRTC();
  LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB);
  LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_RTCAPBAMEN);

  /* RTC interrupt Init */
  NVIC_SetPriority(RTC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(RTC_IRQn);

  RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
  RTC_InitStruct.AsynchPrescaler = 127;
  RTC_InitStruct.SynchPrescaler = 255;
  LL_RTC_Init(RTC, &RTC_InitStruct);
  LL_RTC_SetBackupRegisterPrivilege(RTC, LL_RTC_PRIVILEGE_BKUP_ZONE_NONE);
  LL_RTC_SetBackupRegProtection(RTC, LL_RTC_BKP_DR0, LL_RTC_BKP_DR0);
  LL_RTC_SetRtcPrivilege(RTC, LL_RTC_PRIVILEGE_FULL_NO);

  /** Initialize RTC and set the Time and Date
  */
  if(LL_RTC_BKP_GetRegister(RTC,LL_RTC_BKP_DR0) != 0x32F2){

    LL_RTC_BKP_SetRegister(RTC,LL_RTC_BKP_DR0,0x32F2);
  }
  RTC_TimeStruct.Hours = 0x0;
  RTC_TimeStruct.Minutes = 0x0;
  RTC_TimeStruct.Seconds = 0x0;

  LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_TimeStruct);
  RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_MONDAY;
  RTC_DateStruct.Month = LL_RTC_MONTH_JANUARY;
  RTC_DateStruct.Day = 0x1;
  RTC_DateStruct.Year = 0x0;

  LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_DateStruct);

  /** Enable the Alarm A
  */
  RTC_AlarmStruct.AlarmTime.Hours = 0x1;
  RTC_AlarmStruct.AlarmTime.Minutes = 0x23;
  RTC_AlarmStruct.AlarmTime.Seconds = 0x30;
  RTC_AlarmStruct.AlarmMask = LL_RTC_ALMA_MASK_NONE;
  RTC_AlarmStruct.AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE;
  RTC_AlarmStruct.AlarmDateWeekDay = 0x1;
  LL_RTC_ALMA_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_AlarmStruct);
  LL_RTC_EnableIT_ALRA(RTC);
  LL_RTC_DisableAlarmPullUp(RTC);
}
system_status_t mx_rtc_init(void)
{
  /* Disable RTC Domain Write Protection */
  LL_PWR_DisableRTCDomainWriteProtection();

  /* Clock configuration */
  /* Reset backup domain */
  LL_RCC_ForceRTCDomainReset();
  LL_RCC_ReleaseRTCDomainReset();

  LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);

  LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB);
  LL_RCC_EnableRTC();

  /* Disable write protection */
  LL_RTC_DisableWriteProtection();

  /* Enter init mode */
  uint32_t timeout = 1000;
  if (LL_RTC_IsActiveFlag_INIT() == 0U)
  {
    LL_RTC_EnableInitMode();
    while (LL_RTC_IsActiveFlag_INIT() != 1)
    {
      LL_Delay_NoISR(1);
      timeout--;
      if (timeout == 0)
      {
        return SYSTEM_PERIPHERAL_ERROR;
      }
    }
  }

  /* Configure RTC prescalers and mode */
  uint32_t asynchronous_prescaler = 127;
  uint32_t synchronous_prescaler = 255;

  LL_RTC_SetPrescalers(asynchronous_prescaler, synchronous_prescaler);
  LL_RTC_SetConfigBinaryMode(LL_RTC_BINARY_NONE, LL_RTC_BINARY_MIX_BCDU_0);

  /* Configure calendar */
  uint32_t calendar_date = 0x1;
  uint32_t calendar_hours = 0x0;
  uint32_t calendar_minutes = 0x0;
  uint32_t calendar_seconds = 0x0;

  LL_RTC_SetHourFormatAndShadowRegBypass(LL_RTC_HOUR_FORMAT_24HOUR, LL_RTC_SHADOW_REG_KEEP);
  LL_RTC_DATE_Config(LL_RTC_WEEKDAY_MONDAY, calendar_date, LL_RTC_MONTH_JANUARY, 0x0);
  LL_RTC_TIME_Config(LL_RTC_TIME_FORMAT_AM_24H, calendar_hours, calendar_minutes, calendar_seconds);

  /* Exit init mode */
  timeout = 1000;
  LL_RTC_DisableInitMode();
  if (LL_RTC_IsEnabledBypassShadowReg() == 0U)
  {
    if (LL_RTC_IsActiveFlag_INIT() == 0U)
    {
      LL_RTC_ClearFlag_RS();
      while (LL_RTC_IsActiveFlag_RS() == 0U)
      {
        LL_Delay_NoISR(1) ;
        timeout--;
        if (timeout == 0)
        {
          return SYSTEM_PERIPHERAL_ERROR;
        }
      }
    }
  }

  /* Configure alarm A */
  uint32_t alarm_a_date = 0x1;
  uint32_t alarm_a_hours = 0x1;
  uint32_t alarm_a_minutes = 0x23;
  uint32_t alarm_a_seconds = 0x30;
  uint32_t alarm_a_subseconds = 0;
  uint32_t alarm_a_mask_subseconds = 0;
  uint32_t alarm_a_mask;
  alarm_a_mask = LL_RTC_ALMA_MASK_NONE;

  LL_RTC_ALM_SetConfigDateTime(LL_RTC_ALARM_A, alarm_a_mask, LL_RTC_ALMA_DATEWEEKDAYSEL_DATE, alarm_a_date, LL_RTC_ALMA_TIME_FORMAT_AM_24H, alarm_a_hours, alarm_a_minutes, alarm_a_seconds);
  LL_RTC_ALM_SetConfigSubSecond(LL_RTC_ALARM_A, alarm_a_mask_subseconds, alarm_a_subseconds);

  /* Enable write protection */
  LL_RTC_EnableWriteProtection();

  /* Enable RTC Domain Write Protection */
  LL_PWR_EnableRTCDomainWriteProtection();

  /* Enable the interruption for RTC */
  NVIC_SetPriority(RTC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
  NVIC_EnableIRQ(RTC_IRQn);

  return SYSTEM_OK;
}

Deinit sequence function

void MX_RTC_DeInit(void)
{
  NVIC_DisableIRQ(RTC_IRQn);
}
void mx_rtc_deinit(void)
{
  /* Disable the interruption for RTC */
  NVIC_DisableIRQ(RTC_IRQn);
}

Generated RTC initialization sequences

The RTC initialization sequence is generated in the mx_rtc_hal_init function in mx_rtc.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

STM32CubeMX2 Generated with default values

Topic

HAL1 code snippet

HAL2 code snippet

Initialization and configuration sequence

static void MX_RTC_Init(void)
{
  LL_RTC_InitTypeDef RTC_InitStruct = {0};

  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the peripherals clock  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }

  /* Peripheral clock enable */
  LL_RCC_EnableRTC();
  LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB);
  LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_RTCAPBAMEN);

  RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
  RTC_InitStruct.AsynchPrescaler = 127;
  RTC_InitStruct.SynchPrescaler = 255;
  LL_RTC_Init(RTC, &RTC_InitStruct);
  LL_RTC_SetBackupRegisterPrivilege(RTC, LL_RTC_PRIVILEGE_BKUP_ZONE_NONE);
  LL_RTC_SetBackupRegProtection(RTC, LL_RTC_BKP_DR0, LL_RTC_BKP_DR0);
  LL_RTC_SetRtcPrivilege(RTC, LL_RTC_PRIVILEGE_FULL_NO);
 }
system_status_t mx_rtc_init(void)
{
  /* Disable RTC Domain Write Protection */
  LL_PWR_DisableRTCDomainWriteProtection();

  /* Clock configuration */
  /* Reset backup domain */
  LL_RCC_ForceRTCDomainReset();
  LL_RCC_ReleaseRTCDomainReset();

  LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);

  LL_APB3_GRP1_EnableClock(LL_APB3_GRP1_PERIPH_RTCAPB);
  LL_RCC_EnableRTC();

  /* Disable write protection */
  LL_RTC_DisableWriteProtection();

  /* Enter init mode */
  uint32_t timeout = 1000;
  if (LL_RTC_IsActiveFlag_INIT() == 0U)
  {
    LL_RTC_EnableInitMode();
    while (LL_RTC_IsActiveFlag_INIT() != 1)
    {
      LL_Delay_NoISR(1);
      timeout--;
      if (timeout == 0)
      {
        return SYSTEM_PERIPHERAL_ERROR;
      }
    }
  }

  /* Configure RTC prescalers and mode */
  uint32_t asynchronous_prescaler = 127;
  uint32_t synchronous_prescaler = 255;

  LL_RTC_SetPrescalers(asynchronous_prescaler, synchronous_prescaler);
  LL_RTC_SetConfigBinaryMode(LL_RTC_BINARY_NONE, LL_RTC_BINARY_MIX_BCDU_0);

  /* Exit init mode */
  timeout = 1000;
  LL_RTC_DisableInitMode();
  if (LL_RTC_IsEnabledBypassShadowReg() == 0U)
  {
    if (LL_RTC_IsActiveFlag_INIT() == 0U)
    {
      LL_RTC_ClearFlag_RS();
      while (LL_RTC_IsActiveFlag_RS() == 0U)
      {
        LL_Delay_NoISR(1) ;
        timeout--;
        if (timeout == 0)
        {
          return SYSTEM_PERIPHERAL_ERROR;
        }
      }
    }
  }

  /* Enable write protection */
  LL_RTC_EnableWriteProtection();

  /* Enable RTC Domain Write Protection */
  LL_PWR_EnableRTCDomainWriteProtection();

  /* Enable the interruption for RTC */
  NVIC_SetPriority(RTC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
  NVIC_EnableIRQ(RTC_IRQn);

  return SYSTEM_OK;
 }

Method 2: Replace manually the initialization and de-initialization functions

LL_RTC_Init() API migration

RTC Mode Comparison between HAL1 and HAL2

HAL1

HAL2

LL_RTC_InitTypeDef rtc_InitStruct;

RTC_InitStruct.HourFormat      = LL_RTC_HOURFORMAT_24HOUR;
RTC_InitStruct.AsynchPrescaler = 127;
RTC_InitStruct.DigitalFilter   = 255;

LL_RTC_Init(RTC, &rtc_InitStruct);
LL_RTC_DisableWriteProtection();

LL_RTC_EnableInitMode();
LL_RTC_TIME_SetFormat(RTC, LL_RTC_TIME_FORMAT_AM_24H);
LL_RTC_SetSynchPrescaler(RTC, 127);
LL_RTC_SetAsynchPrescaler(RTC, 255);
LL_RTC_DisableInitMode();

LL_RTC_EnableWriteProtection(void)

LL_RTC_DeInit() API migration

Comparison of HAL1 and HAL2

HAL1

HAL2

LL_RTC_DeInit(RTC)
LL_RTC_DisableWriteProtection();

LL_RTC_EnableInitMode();

LL_RTC_WRITE_REG(RTC->TR,       0U);
LL_RTC_WRITE_REG(RTC->DR, (RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0));
LL_RTC_WRITE_REG(RTC->CR,       0U);
LL_RTC_WRITE_REG(RTC->WUTR,     RTC_WUTR_WUT);
LL_RTC_WRITE_REG(RTC->PRER, (RTC_PRER_PREDIV_A | RTC_SYNCH_PRESC_DEFAULT));
LL_RTC_WRITE_REG(RTC->ALRMAR,   0U);
LL_RTC_WRITE_REG(RTC->ALRMBR,   0U);
LL_RTC_WRITE_REG(RTC->SHIFTR,   0U);
LL_RTC_WRITE_REG(RTC->CALR,     0U);
LL_RTC_WRITE_REG(RTC->ALRMASSR, 0U);
LL_RTC_WRITE_REG(RTC->ALRMBSSR, 0U);

LL_RTC_DisableInitMode();